﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace CobaCoba
{
    public class TimerThread
    {
        #region Delegates

        public delegate void TimerFiredEventHandler(object sender, TimerFiredArgs args);

        #endregion

        private int intv;
        //private const string TLS_NAME = "TimerCtxUserCtx";
        private bool isRunning;
        private volatile bool isSignalClose;
        private Timer tmr;
        private volatile object userCntx;

        public TimerThread()
        {
            Name = GetHashCode().ToString("X8", Thread.CurrentThread.CurrentCulture);
        }


        ~TimerThread()
        {
            if (tmr != null)
            {
                try
                {
                    tmr.Change(intv, Timeout.Infinite);

                }
                catch (Exception ex)
                {
                    Console.WriteLine(
                       string.Format("TimerThread:~CTimerThread Change - {0}", ex.Message));
                }

                try
                {
                    tmr.Dispose();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(
                       string.Format("TimerThread:~CTimerThread Dispose - {0}", ex.Message));
                }
            }
        }

        public string Name { get; set; }

        public bool IsRunning
        {
            get { return isRunning; }
        }

        public int Interval
        {
            get { return intv; }
            set
            {
                intv = value;
                if (tmr != null)
                {
                    try
                    {
                        tmr.Change(intv, Timeout.Infinite);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(
                           string.Format("TimerThread:Interval - {0}", ex.Message));
                    }
                }
            }
        }

        public event TimerFiredEventHandler TimerFired;

        private void OnTimerFired()
        {
            if ((TimerFired != null) && (isRunning))
            {
                TimerFiredArgs tfa = new TimerFiredArgs(userCntx);

                TimerFired(this, tfa);
            }
        }

        private void TimerCB(object state)
        {
            if (isSignalClose)
                return;

            AutoResetEvent are = (AutoResetEvent)state;

            //mre.Reset();

            OnTimerFired();

            are.Set();
            try
            {
                
                tmr.Change(intv, Timeout.Infinite);
            }
            catch (Exception ex)
            {
                Console.WriteLine(
                   string.Format("TimerThread:TimerCB - {0}", ex.Message));
            }
        }

        public void Start()
        {
            if (tmr != null)
                tmr.Dispose();

            tmr = new Timer (TimerCB, new AutoResetEvent(false), 0, 0);
            isRunning = true;
        }

        public void Start(object userContext)
        {
            userCntx = userContext;

            if (tmr != null)
                tmr.Dispose();

            tmr = new Timer(TimerCB, new AutoResetEvent(false), intv, Timeout.Infinite);
            isRunning = true;
        }

        public void Start(object userContext, int interval)
        {
            userCntx = userContext;

            intv = interval;

            if (tmr != null)
                tmr.Dispose();

            tmr = new Timer(TimerCB, new AutoResetEvent(false), interval, Timeout.Infinite);
            isRunning = true;
        }

        public void Stop()
        {
            isSignalClose = true;
            isRunning = false;
            if (tmr != null)
            {
                try
                {
                    tmr.Change(Timeout.Infinite, Timeout.Infinite);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(
                       string.Format("TimerThread:Stop - {0}", ex.Message));
                }
            }
        }

        public void Pause()
        {
            isRunning = false;
            try
            {
                tmr.Change(Timeout.Infinite, Timeout.Infinite);
            }
            catch (Exception ex)
            {
                Console.WriteLine(
                   string.Format("TimerThread:Pause - {0}", ex.Message));
            }
        }

        public void Resume()
        {
            isRunning = true;
            try
            {
                tmr.Change(intv, Timeout.Infinite);
            }
            catch (Exception ex)
            {
                Console.WriteLine(
                   string.Format("TimerThread:Resume - {0}", ex.Message));
            }
        }

        public void UpdateUserContext(object context)
        {
            userCntx = context;
        }
    }

    public class TimerFiredArgs : EventArgs
    {
        private readonly object uc;

        internal TimerFiredArgs(object userCtx)
        {
            uc = userCtx;
        }

        public object UserContext
        {
            get { return uc; }
        }
    }
}


